#ifndef UTIL_LAMBDAVISITOR_H_
#define UTIL_LAMBDAVISITOR_H_

#include <boost/variant/static_visitor.hpp>


namespace util {



template <class ReturnType, class Lambda1>
struct lambda_visitor :
  public boost::static_visitor<ReturnType>, public Lambda1 {

  typedef boost::static_visitor<ReturnType> BaseVisitor;

  using Lambda1::operator();
  lambda_visitor(Lambda1 l1) 
    : BaseVisitor(), Lambda1(l1) {
  }
};

template <class ReturnType = void, class Lambda1>
lambda_visitor<ReturnType, Lambda1> make_lambda_visitor(Lambda1 l1) {
	return lambda_visitor<ReturnType, Lambda1>(l1);
}




template <class ReturnType, class Lambda1, class Lambda2>
struct lambda_visitor2 :
  public lambda_visitor<ReturnType, Lambda1>, public Lambda2 {

  typedef lambda_visitor<ReturnType, Lambda1> BaseVisitor;

  using BaseVisitor::operator();
  using Lambda2::operator();
  lambda_visitor2(Lambda1 l1, Lambda2 l2) 
    : BaseVisitor(l1), Lambda2(l2) {
  }
};

template <class ReturnType = void, class Lambda1, class Lambda2>
lambda_visitor2<ReturnType, Lambda1, Lambda2> make_lambda_visitor(
    Lambda1 l1, Lambda2 l2) {
  return lambda_visitor2<ReturnType, Lambda1, Lambda2>(l1, l2);
}




template <class ReturnType, class Lambda1, class Lambda2, class Lambda3>
struct lambda_visitor3 :
  public lambda_visitor2<ReturnType, Lambda1, Lambda2>, public Lambda3 {

  typedef lambda_visitor2<ReturnType, Lambda1, Lambda2> BaseVisitor;

  using BaseVisitor::operator();
  using Lambda3::operator();
  lambda_visitor3(Lambda1 l1, Lambda2 l2, Lambda3 l3) 
    : BaseVisitor(l1, l2), Lambda3(l3) {
  }
};

template <class ReturnType = void, class Lambda1, class Lambda2, class Lambda3>
lambda_visitor3<ReturnType, Lambda1, Lambda2, Lambda3> make_lambda_visitor(
    Lambda1 l1, Lambda2 l2, Lambda3 l3) {
  return lambda_visitor3<ReturnType, Lambda1, Lambda2, Lambda3>(l1, l2, l3);
}




template <class R, class L1, class L2, class L3, class L4>
struct lambda_visitor4 :
  public lambda_visitor3<R, L1, L2, L3>, public L4 {

  typedef lambda_visitor3<R, L1, L2, L3> BaseVisitor;

  using BaseVisitor::operator();
  using L4::operator();
  lambda_visitor4(L1 l1, L2 l2, L3 l3, L4 l4) 
    : BaseVisitor(l1, l2, l3), L4(l4) {
  }
};

template <class R = void, class L1, class L2, class L3, class L4>
lambda_visitor4<R, L1, L2, L3, L4> make_lambda_visitor(
    L1 l1, L2 l2, L3 l3, L4 l4) {
  return lambda_visitor4<R, L1, L2, L3, L4>(l1, l2, l3, l4);
}




} // namespace util

#endif // UTIL_LAMBDAVISITOR_H_

